package com.qianfeng.iot.sdk.service.rabbit;

//
//                            _ooOoo_  
//                           o8888888o  
//                           88" . "88  
//                           (| -_- |)  
//                            O\ = /O  
//                        ____/`---'\____  
//                      .   ' \\| |// `.  
//                       / \\||| : |||// \  
//                     / _||||| -:- |||||- \  
//                       | | \\\ - /// | |  
//                     | \_| ''\---/'' | |  
//                      \ .-\__ `-` ___/-. /  
//                   ___`. .' /--.--\ `. . __  
//                ."" '< `.___\_<|>_/___.' >'"".  
//               | | : `- \`.;`\ _ /`;.`/ - ` : | |  
//                 \ \ `-. \_ __\ /__ _/ .-` / /  
//         ======`-.____`-.___\_____/___.-`____.-'======  
//                            `=---='  
//  
//         .............................................  
//                  佛祖镇楼                  BUG辟易  
//          佛曰:  
//                  写字楼里写字间，写字间里程序员；  
//                  程序人员写程序，又拿程序换酒钱。  
//                  酒醒只在网上坐，酒醉还来网下眠；  
//                  酒醉酒醒日复日，网上网下年复年。  
//                  但愿老死电脑间，不愿鞠躬老板前；  
//                  奔驰宝马贵者趣，公交自行程序员。  
//                  别人笑我忒疯癫，我笑自己命太贱；  
//  


import cn.hutool.core.convert.Convert;
import com.dc3.common.bean.driver.DriverConfiguration;
import com.dc3.common.bean.driver.DriverMetadata;
import com.dc3.common.constant.CommonConstant;
import com.dc3.common.model.*;
import com.dc3.common.utils.JsonUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qianfeng.iot.sdk.bean.driver.DriverContext;
import com.qianfeng.iot.sdk.service.DriverMetadataService;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;

/**
 * Created by Jackiechan on 2022/7/27 10:19
 *
 * @author Jackiechan
 * @version 1.0
 * @since 1.0
 */
@Component
@Slf4j
public class DriverMetadataReceiver {

    private ObjectMapper objectMapper;

    @Autowired
    public void setObjectMapper(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    private DriverContext driverContext;

    @Autowired
    public void setDriverContext(DriverContext driverContext) {
        this.driverContext = driverContext;
    }


    private DriverMetadataService driverMetadataService;

    @Autowired
    public void setDriverMetadataService(DriverMetadataService driverMetadataService) {
        this.driverMetadataService = driverMetadataService;
    }

    //metaDataQueue指的是在spring管理的对象中有一个名字叫metaDataQueue的对象,从里面获取了name属性
    //经过我们分析,我们驱动中的数据发生变化我们这边也需要更新,那我们需要知道当前收到的消息是什么类型的消息
    //比如是位号相关的还是设备相关的还是驱动信息相关的,因为不同的操作需要修改不同的数据
    @RabbitListener(queues = "#{metaDataQueue.name}")
    public void onDriverConfigMessage(Channel channel, Message message, DriverConfiguration driverConfiguration) {
        //应答消息
        try {
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        //  System.err.println("收到了来自于manager的消息:" + driverConfiguration);
        switch (driverConfiguration.getType()) {
            case CommonConstant.Driver.Type.DRIVER:
                configDriverMeata(driverConfiguration);
                break;
            case CommonConstant.Driver.Type.POINT_INFO:
                configPointInfo(driverConfiguration);
                break;

            case CommonConstant.Driver.Type.PROFILE:
                configurationProfile(driverConfiguration);
                break;
            case CommonConstant.Driver.Type.DEVICE:
                configurationDevice(driverConfiguration);
                break;
            case CommonConstant.Driver.Type.POINT:
                configurationPoint(driverConfiguration);
                break;
            case CommonConstant.Driver.Type.DRIVER_INFO:
                configurationDriverInfo(driverConfiguration);
                break;
            default:
                break;
        }


    }



    /**
     * 配置 driver profile
     *
     * @param driverConfiguration DriverConfiguration
     */
    private void configurationProfile(DriverConfiguration driverConfiguration) {
        Profile profile = Convert.convert(Profile.class, driverConfiguration.getContent());
        if (CommonConstant.Driver.Profile.ADD.equals(driverConfiguration.getCommand()) || CommonConstant.Driver.Profile.UPDATE.equals(driverConfiguration.getCommand())) {
            log.info("Upsert profile \n{}", JsonUtil.toJsonString(profile));
            driverMetadataService.upsertProfile(profile);
        } else if (CommonConstant.Driver.Profile.DELETE.equals(driverConfiguration.getCommand())) {
            log.info("Delete profile {}", profile.getName());
            driverMetadataService.deleteProfile(profile.getId());
        }
    }

    /**
     * 配置 driver device
     *
     * @param driverConfiguration DriverConfiguration
     */
    private void configurationDevice(DriverConfiguration driverConfiguration) {
        Device device = Convert.convert(Device.class, driverConfiguration.getContent());
        if (CommonConstant.Driver.Device.ADD.equals(driverConfiguration.getCommand()) || CommonConstant.Driver.Device.UPDATE.equals(driverConfiguration.getCommand())) {
            log.info("Upsert device \n{}", JsonUtil.toJsonString(device));
            driverMetadataService.upsertDevice(device);
        } else if (CommonConstant.Driver.Device.DELETE.equals(driverConfiguration.getCommand())) {
            log.info("Delete device {}", device.getName());
            driverMetadataService.deleteDevice(device.getId());
        }
    }

    /**
     * 配置 driver point
     *
     * @param driverConfiguration DriverConfiguration
     */
    private void configurationPoint(DriverConfiguration driverConfiguration) {
        Point point = Convert.convert(Point.class, driverConfiguration.getContent());
        if (CommonConstant.Driver.Point.ADD.equals(driverConfiguration.getCommand()) || CommonConstant.Driver.Point.UPDATE.equals(driverConfiguration.getCommand())) {
            log.info("Upsert point \n{}", JsonUtil.toJsonString(point));
            driverMetadataService.upsertPoint(point);
        } else if (CommonConstant.Driver.Point.DELETE.equals(driverConfiguration.getCommand())) {
            log.info("Delete point {}", point.getName());
            driverMetadataService.deletePoint(point.getProfileId(), point.getId());
        }
    }

    /**
     * 配置 driver info
     *
     * @param driverConfiguration DriverConfiguration
     */
    private void configurationDriverInfo(DriverConfiguration driverConfiguration) {
        DriverInfo driverInfo = Convert.convert(DriverInfo.class, driverConfiguration.getContent());
        if (CommonConstant.Driver.DriverInfo.ADD.equals(driverConfiguration.getCommand()) || CommonConstant.Driver.DriverInfo.UPDATE.equals(driverConfiguration.getCommand())) {
            log.info("Upsert driver info \n{}", JsonUtil.toJsonString(driverInfo));
            driverMetadataService.upsertDriverInfo(driverInfo);
        } else if (CommonConstant.Driver.DriverInfo.DELETE.equals(driverConfiguration.getCommand())) {
            log.info("Delete driver info {}", driverInfo);
            driverMetadataService.deleteDriverInfo(driverInfo.getDeviceId(), driverInfo.getDriverAttributeId());
        }
    }



    /**
     * 配置位号信息.主要就是针对位号的增删改查
     *
     * @param driverConfiguration
     */
    private void configPointInfo(DriverConfiguration driverConfiguration) {
        try {
            PointInfo pointInfo = objectMapper.readValue(objectMapper.writeValueAsString(driverConfiguration.getContent()), PointInfo.class);
            switch (driverConfiguration.getCommand()) {
                //因为添加是保存到map中,更新是从map中替换,操作都是put
                case CommonConstant.Driver.PointInfo.ADD:
                case CommonConstant.Driver.PointInfo.UPDATE:
                    //更新或者插入数据
                    driverMetadataService.upsertPointInfo(pointInfo);
                    break;
                case CommonConstant.Driver.PointInfo.DELETE:
                    driverMetadataService.deletePointInfo(pointInfo);
                    break;
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 和驱动注册相关的操作,包括握手,驱动同步返回
     *
     * @param driverConfiguration
     */
    private void configDriverMeata(DriverConfiguration driverConfiguration) {
        switch (driverConfiguration.getCommand()) {
            case CommonConstant.Driver.Event.DRIVER_REGISTER_BACK:
                //当我们的驱动服务启动起来注册之后返回的结果
                //代表注册成功
                driverContext.setDriverStatus(CommonConstant.Status.ONLINE);
                break;

            case CommonConstant.Driver.Event.DRIVER_METADATA_SYNC_BACK:

                //获取到返回回来的元数据
                Object content = driverConfiguration.getContent();
                try {
                    driverContext.setDriverMetadata(objectMapper.readValue(objectMapper.writeValueAsString(content), DriverMetadata.class));
                } catch (JsonProcessingException e) {
                    throw new RuntimeException(e);
                }
                //设置到driverContext的metadata对象上面
                System.err.println(driverContext.getDriverMetadata());
                break;
        }
    }
}
